JavaScript 56.7%
TypeScript 42.6%
1import { NextRequest, NextResponse } from "next/server";2import { prisma } from "@/lib/prisma";3import { duplicateFile } from "@/lib/storage";4import { logActivity } from "@/lib/activity";5import { getSpaceIdForFolder } from "@/lib/trash";67/** « rapport.pdf » → « rapport (copie).pdf », puis « rapport (copie 2).pdf »… */8async function copyName(original: string, folderId: string | null): Promise<string> {9 const m = original.match(/^(.*?)(\.[^.]+)?$/);10 const stem = m?.[1] ?? original;11 const ext = m?.[2] ?? "";12 const siblings = await prisma.file.findMany({ where: { folderId, deletedAt: null }, select: { name: true } });13 const taken = new Set(siblings.map((s) => s.name.toLowerCase()));14 let candidate = `${stem} (copie)${ext}`;15 for (let i = 2; taken.has(candidate.toLowerCase()); i++) candidate = `${stem} (copie ${i})${ext}`;16 return candidate;17}1819export async function POST(20 request: NextRequest,21 { params }: { params: { id: string } }22) {23 const file = await prisma.file.findUnique({ where: { id: params.id } });2425 if (!file || file.deletedAt) {26 return NextResponse.json({ error: "File not found" }, { status: 404 });27 }2829 // Quota de l'espace partagé (hérité via l'arborescence)30 const spaceId = await getSpaceIdForFolder(file.folderId);31 if (spaceId) {32 const space = await prisma.sharedSpace.findUnique({ where: { id: spaceId } });33 if (space) {34 const agg = await prisma.file.aggregate({ _sum: { size: true }, where: { deletedAt: null, folder: { sharedSpaceId: spaceId } } });35 if (Number(agg._sum.size || 0) + Number(file.size) > Number(space.quotaBytes)) {36 return NextResponse.json({ error: "Quota de l'espace partagé dépassé" }, { status: 413 });37 }38 }39 }4041 const { storagePath } = await duplicateFile(file.storagePath, file.name);4243 const duplicated = await prisma.file.create({44 data: {45 name: await copyName(file.name, file.folderId),46 storagePath,47 // copie octet-à-octet : même état de chiffrement ; on garde la taille en clair d'origine48 size: file.size,49 mimeType: file.mimeType,50 folderId: file.folderId,51 userId: file.userId,52 isEncrypted: file.isEncrypted,53 aiDescription: file.aiDescription,54 aiTags: file.aiTags,55 },56 });5758 await logActivity("UPLOAD", duplicated.id, `Duplicated ${file.name}`);5960 return NextResponse.json(61 { ...duplicated, size: Number(duplicated.size) },62 { status: 201 }63 );64}65